import { getEntityComponents, type IWorld, getAllEntities, createWorld, entityExists, addEntity, removeEntity, type Entity, addComponent, getComponents, defineQuery, getComponent, componentName } from './ecs';
import { $isEidType } from 'bitecs';
import { decode, encode } from './util';
import { afterLoad } from './pos3';

export const entityToObject = (world: IWorld, e: Entity) => {
  const obj = {};
  for (let component of getEntityComponents(world, e)) {
    // console.log(component);
    const compName = componentName(component);
    if (compName === undefined) {
      throw Error("Unnamed component while serializing!");
    }
    obj[compName] = {};
    for (let [key, arr] of Object.entries(component)) {
      if (arr[$isEidType]) {
        obj[compName][key] = arr[e];
      } else if (arr[e] instanceof Uint8Array) {
        obj[compName][key] = decode(arr[e]);
      } else {
        obj[compName][key] = arr[e];
      }
    }
  }
  return obj;
};

export const worldToObject = (world: IWorld) => {
  const objs = {};
  for (let e of getAllEntities(world)) {
    objs[e] = entityToObject(world, e);
  }
  return objs;
};

export const worldFromObject = (obj) => {
  const world = createWorld();
  const mapping = new Map();
  console.log('load loop');
  for (let [e, comps] of Object.entries(obj)) {
    // console.log(e, comps);
    const e1 = addEntity(world);
    mapping.set(e, e1);
    for (let [comp, vals] of Object.entries(comps)) {
      const component = getComponent(comp);
      // console.log(comp, component);
      addComponent(world, component, e1);
      for (let [name, val] of Object.entries(vals)) {
        if (component[name][$isEidType]) {
          component[name][e1] = val;
        } else if (typeof val === 'string') {
          component[name][e1] = encode(val);
        } else {
          component[name][e1] = val;
        }
      }
    }
  }
  console.log('Loaded props');
  for (let comp of getComponents()) {
    for (let [name, arr] of Object.entries(comp)) {
      if (arr[$isEidType]) {
        for (let e of defineQuery([comp])(world)) {
          console.log(typeof arr);
        }
      }
    }
  }
  afterLoad(world);
  console.log('LOADED');
  return world;
};
